package IC.Analyzer;

import java.util.Stack;


import IC.AST.ASTNode;
import IC.AST.ASTPrinter;
import IC.AST.nodes.ClassDecl;
import IC.Analyzer.Types.*;

public class SymTabPrinter extends ASTPrinter {
	private Stack<SymTable> prev;

	public SymTabPrinter(ASTNode symbol) {
		super(symbol);
		prev = new Stack<SymTable>();
		prev.push(null);
		depth=0;
	}

	/**
	 * Print type tables and all symtabs
	 */
	@Override
	public void print() throws Exception {
		System.out.println("\nType Table:");
		System.out.println("============");

		// primitives

		String _bool = BoolType.toStringAll();
		String _int = IntType.toStringAll();
		String _str = StringType.toStringAll();
		String _null = NullType.toStringAll();

		System.out.print("\n[\n");

		System.out.print((_bool!=null)?_bool+"\n":"");
		System.out.print((_int!=null)?_int+"\n":"");
		System.out.print((_str!=null)?_str+"\n":"");
		System.out.print((_null!=null)?_null+"\n":"");
		System.out.print("]\n");

		// complex types
		System.out.print("\n[\n"+MethodType.toStringAll()+"]\n");
		System.out.print("\n[\n"+ClassType.toStringAll()+"]\n");
		System.out.print("\n[\n"+ArrayType.toStringAll()+"]\n");


		System.out.println("\nSymbol Tables:");
		System.out.println("==============");

		depth = 1;
		root.accept(this,null);
	}

	protected void enter(String header, ASTNode node) {

		SymTable symtab = node.getSymTab();
		SymTable stat_symtab = null;
		
		if(node instanceof ClassDecl) {
			stat_symtab = ((ClassDecl)node).getStaticSymTab();
		}

		if (symtab != prev.peek()) {

			System.out.println(SPACES.substring(0,depth*ident)+header);
			String symtabStr = symtab.toString() +"\n"+ ((stat_symtab!=null)?stat_symtab.toString():"");
			String[] splitSymtabStr = symtabStr.split("\n");
			for(String s : splitSymtabStr) {
				System.out.println(
						SPACES.substring(0,(depth/*+1*/)*ident/*+1*/) + 
						s );			
			}
			System.out.println();
			
		}
		depth ++;
		prev.push(symtab);
	}

	protected void enterLeave(String header, ASTNode node) {

		SymTable symtab = node.getSymTab();

		if (symtab != prev.peek()) {
			System.out.println(symtab);
			System.out.println(ASTPrinter.SPACES.substring(0,depth*ident));
			System.out.println();
		}

	}

	protected void leave() {
		depth --;
		prev.pop();
	}
}
